package com.milling.common.utils.modbus;

import com.serotonin.modbus4j.ModbusMaster;
import org.apache.commons.pool2.ObjectPool;
import org.apache.commons.pool2.impl.GenericObjectPool;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class ModbusServiceFactory {
    // 使用 ConcurrentHashMap 存储不同 PLC 的连接服务
    private static final Map<String, ModbusTcpService> serviceMap = new ConcurrentHashMap<>();

    /**
     * 获取指定 PLC 的 Modbus 服务
     *
     * @param host PLC 的 IP 地址
     * @param port PLC 的端口号
     * @param poolSize 连接池大小
     * @return ModbusTcpService 实例
     */
    public static ModbusTcpService getModbusService(String host, int port, int poolSize) {
        // 生成唯一的 PLC 标识
        String plcKey = generatePlcKey(host, port);

        // 双重检查锁确保线程安全
        if (!serviceMap.containsKey(plcKey)) {
            synchronized (ModbusServiceFactory.class) {
                if (!serviceMap.containsKey(plcKey)) {
                    // 创建连接池
                    GenericObjectPool<ModbusMaster> pool =
                            ModbusMasterPoolFactory.createPool(host, port, poolSize);

                    // 创建服务实例并存入缓存
                    ModbusTcpService service = new ModbusTcpServiceImpl(pool);
                    serviceMap.put(plcKey, service);
                }
            }
        }
        return serviceMap.get(plcKey);
    }

    /**
     * 获取指定 PLC 的 Modbus 服务（使用默认连接池大小）
     *
     * @param host PLC 的 IP 地址
     * @param port PLC 的端口号
     * @return ModbusTcpService 实例
     */
    public static ModbusTcpService getModbusService(String host, int port) {
        // 使用默认连接池大小
        return getModbusService(host, port, 5); // 默认连接池大小
    }

    /**
     * 生成 PLC 的唯一标识键
     *
     * @param host IP 地址
     * @param port 端口号
     * @return 格式化的键字符串
     */
    private static String generatePlcKey(String host, int port) {
        return host + ":" + port;
    }

    /**
     * 关闭所有 PLC 连接池（应用关闭时调用）
     */
    public static void shutdownAll() {
        for (ModbusTcpService service : serviceMap.values()) {
            try {
                if (service instanceof ModbusTcpServiceImpl) {
                    ((ModbusTcpServiceImpl) service).close();
                }
            } catch (Exception e) {
                // 记录错误但继续关闭其他连接
                e.printStackTrace();
            }
        }
        serviceMap.clear();
    }
}
